﻿using System;
using System.IO;
using System.Net;
using System.Threading;
using Microsoft.Xna.Framework.Media.PhoneExtensions;
using SAFPodcast.WP8.DTO.TO;
using SAFPodcast.WP8.Fwk.Helper;

namespace SAFPodcast.WP8.DAL.Web
{
    public class WebAO : IWebAO
    {
        public const Int32 MAX_PERCENTAGE = 100;
        public const Int32 CANCELED_PERCENTAGE = -1;

        public void Validade(Uri uri, Action<bool> callback)
        {
            var waitHandle = new ManualResetEvent(false);
            bool timedOut = false;
            var syncLock = new object();
            var request = HttpWebRequest.CreateHttp(uri);
            request.Method = "HEAD";

            #region Web request Callback
            Action<IAsyncResult> webRequestCallback = (result) =>
            {
                lock (syncLock)
                {
                    if (waitHandle != null)
                    {
                        waitHandle.Reset();
                        waitHandle.Dispose();
                        waitHandle = null;
                        if (!timedOut)
                        {
                            try
                            {
                                using (var response = request.EndGetResponse(result) as HttpWebResponse)
                                {
                                    var statusCode = (int)response.StatusCode;
                                    var success = statusCode >= 100 && statusCode < 400;
                                    callback(success);
                                }
                            }
                            catch (WebException)
                            {
                                callback(false);
                            }
                        }
                    }
                }
            };
            #endregion

            request.BeginGetResponse(new AsyncCallback(webRequestCallback), null);

            new Thread(() =>
            {
                waitHandle.Reset();
                bool signalled = waitHandle.WaitOne(5000);
                lock (syncLock)
                {
                    if (waitHandle != null)
                    {
                        waitHandle.Dispose();
                        waitHandle = null;
                        if (!signalled)
                        {
                            request.Abort();
                            timedOut = true;
                            callback(false);
                        }
                    }
                }
            }).Start();
        }

        public void DownloadSingleFile(SongMetadata song, Uri uri, Action<DownloadDataItem, Exception> callback)
        {
            var client = new WebClient();
            #region DownloadProgressChanged
            client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(
                (src, e) => callback(new DownloadDataItem(e.ProgressPercentage, null, false, song), null));
            #endregion
            client.AllowReadStreamBuffering = true;
            #region OpenReadCompleted
            client.OpenReadCompleted += new OpenReadCompletedEventHandler((src, e) =>
            {
                try
                {
                    Stream stream = null;
                    int percent = CANCELED_PERCENTAGE;

                    if (e.Error != null)
                    {
                        callback(null, e.Error);
                    }
                    else
                    {
                        if (!e.Cancelled)
                        {
                            stream = e.Result;
                            percent = MAX_PERCENTAGE;
                        }
                        callback(new DownloadDataItem(percent, stream, e.Cancelled, song), null);
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Error("Echec lors du download d'un fichier unique", ex);
                    callback(null, ex);
                }
            });
            #endregion

            client.OpenReadAsync(uri);
        }

        public void DownloadFeedText(Uri uri, Action<string, Exception> callback)
        {
            WebClient client = new WebClient();
            client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(
                (src, e) => {
                    if (e.Cancelled || e.Error != null)
                    {
                        callback(null, e.Error);
                    }
                    else
                    {
                        callback(e.Result, null);
                    }
                });
            client.DownloadStringAsync(uri);
        }
    }
}
